use crate::matrix;
use crate::vector::vector::Vector;

#[test]
fn create_matrix() {
    let mut mat = matrix!(4, 4);
    let data = vec![
        0.0, 0.0, 5.0, 0.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0,
    ];
    mat.set_data(data);
    println!("{:?}", mat);
    let identity_mat = mat.identity();
    println!("{:?}", identity_mat);
}

#[test]
fn add_matrix() {
    let mut mat1 = matrix!(2, 4);
    let data1 = vec![1.0, 3.0, 5.0, 7.0, 2.0, 4.0, 6.0, 8.0];
    mat1.set_data(data1);
    let mut mat2 = matrix!(2, 4);
    let data2 = vec![4.0, 3.0, 1.0, 4.0, 5.0, 3.0, 1.0, 6.0];
    mat2.set_data(data2);
    println!("{:?}", mat1 + mat2);
}

#[test]
fn sub_matrix() {
    let mut mat1 = matrix!(2, 4);
    let data1 = vec![1.0, 3.0, 5.0, 7.0, 2.0, 4.0, 6.0, 8.0];
    mat1.set_data(data1);
    let mut mat2 = matrix!(2, 4);
    let data2 = vec![4.0, 3.0, 1.0, 4.0, 5.0, 3.0, 1.0, 6.0];
    mat2.set_data(data2);
    println!("{:?}", mat1 - mat2);
}

#[test]
fn mul_matrix_vector() {
    let mut mat = matrix!(3, 4);
    let data = vec![
        2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0, 19.0, 23.0, 29.0, 31.0, 37.0,
    ];
    mat.set_data(data);

    println!("{:?}", mat);

    let vector = Vector::new(vec![1.0, 2.0, 3.0, 4.0]);

    let vector1 = mat * vector;
    println!("{:?}", vector1);
}

#[test]
fn mul_matrix_matrix() {
    let mut a = matrix!(2, 3);
    let a_data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];

    let mut b = matrix!(3, 2);
    let b_data = vec![7.0, 8.0, 9.0, 10.0, 11.0, 12.0];

    a.set_data(a_data);
    b.set_data(b_data);

    println!("{:?}", a * b);
}

#[test]
fn transpose() {
    let mut mat1 = matrix!(2, 4);
    let data1 = vec![1.0, 3.0, 5.0, 7.0, 2.0, 4.0, 6.0, 8.0];
    mat1.set_data(data1);
    let mat2 = mat1.transpose();
    let mat3 = mat2.transpose();
    println!("{:?}", mat2);
    println!("{:?}", mat3);
}

#[test]
fn elimination() {
    let mut a = matrix!(3, 3);
    let a_data = vec![1.0, 2.0, 1.0, 3.0, 8.0, 1.0, 0.0, 4.0, 1.0];
    a.set_data(a_data);
    let mut b = a.identity();
    b.set_item(1, 0, -a.get_item(1, 0));

    println!("{:?}", b);

    let mut c = a.identity();
    c.set_item(2, 1, -a.get_item(2, 1));

    let n = c * b * a;
    println!("{:?}", n);
}

#[test]
fn replace_row() {
    let mut a = matrix!(3, 3);
    let a_data = vec![1.0, 2.0, 1.0, 3.0, 8.0, 1.0, 0.0, 4.0, 1.0];
    a.set_data(a_data);

    let b = a.replace_row(0, 1);
    println!("{:?}", b);
}

#[test]
fn replace_col() {
    let mut a = matrix!(3, 3);
    let a_data = vec![1.0, 2.0, 1.0, 3.0, 8.0, 1.0, 0.0, 4.0, 1.0];
    a.set_data(a_data);

    let b = a.replace_col(1, 2);
    println!("{:?}", b);
}

#[test]
fn reciprocal() {
    let mut mat = matrix!(3, 3);
    let data = vec![1.0, 2.0, 3.0, 0.0, 1.0, 4.0, 5.0, 6.0, 0.0];
    mat.set_data(data);

    println!("{:?}", mat);
    let reciprocal_mat = mat.reciprocal();
    println!("{:?}", reciprocal_mat);
    println!("{:?}", reciprocal_mat * mat);

    let mut mat1 = matrix!(3, 3);
    let data1 = vec![2.0, -1.0, 0.0, 1.0, 2.0, 1.0, 0.0, -1.0, 1.0];
    mat1.set_data(data1);

    println!("{:?}", mat1);
    let reciprocal_mat1 = mat1.reciprocal();
    println!("{:?}", reciprocal_mat1);
    println!("{:?}", reciprocal_mat1 * mat1);
}

#[test]
fn lu() {
    let mut mat = matrix!(4, 4);
    let data = vec![
        1.0, 2.0, 4.0, 1.0, 2.0, -3.0, -1.0, -1.0, 1.0, 1.0, 4.0, 2.0, 3.0, 2.0, 1.0, -1.0,
    ];
    mat.set_data(data);

    let (l_mat, u_mat) = mat.lu();

    println!("{:?}", mat);
    println!("{:?}", l_mat);
    println!("{:?}", u_mat);
    println!("{:?}", l_mat * u_mat)
}

#[test]
fn tr() {
    let mut mat = matrix!(4, 4);
    let data = vec![
        1.0, 2.0, 4.0, 1.0, 2.0, -3.0, -1.0, -1.0, 1.0, 1.0, 4.0, 2.0, 3.0, 2.0, 1.0, -1.0,
    ];
    mat.set_data(data);

    let tr = mat.tr();

    println!("{:?}", tr);
}
